package com.gemini.main.proxy;

/**
 * 在RPC调用中，DUBBO作者梁飞任务JAVASSIST字节码生成技术的性能是最好的
 * 是因为在梁飞的例子里，会对目标对象delegate进行调用。
 * 而jdk动态代理，cglib动态代理，javaassist动态代理，都会使用反射调用目标对象，
 * 而javaassist字节码生成技术,asm字节码生成技术，则没有使用反射调用目标对象，而是类似装饰器的设计模式，直接调用delegate.method(args)。
 * 所以，性能的差异在于用反射调用方法和直接调用
 *
 * 在RPC调用过程中，客户端需要创建代理对象，但是其实并不需要调用目标方法，只需要拿到方法的元数据发送到服务端即可
 *
 * 服务端在拿到客户端发送过来的元数据的后，其实是需要调用目标方法的，这时候javassist以及asm技术将会提供性能上的优势
 *
 * gemini
 * com.gemini.main.proxy.TestProxy
 *
 * @author zhanghailin
 */
public class TestProxy {

    public static void main(String[] args) throws Exception {
        InvokeHandler handler = new InvokeHandler();
        long time = System.currentTimeMillis();
        ProxyTestService test1 = ProxyEnum.JDK_PROXY.newProxyInstance(ProxyTestService.class, handler);
        time = System.currentTimeMillis() - time;
        System.out.println("Create JDK Proxy: " + time + " ms");
        time = System.currentTimeMillis();
        ProxyTestService test2 = ProxyEnum.BYTE_BUDDY_PROXY.newProxyInstance(ProxyTestService.class, handler);
        time = System.currentTimeMillis() - time;
        System.out.println("Create byteBuddy Proxy: " + time + " ms");
        time = System.currentTimeMillis();
        ProxyTestService test3 = ProxyEnum.CGLIB_PROXY.newProxyInstance(ProxyTestService.class, handler);
        time = System.currentTimeMillis() - time;
        System.out.println("Create CGLIB Proxy: " + time + " ms");
        time = System.currentTimeMillis();
        ProxyTestService test4 = ProxyEnum.JAVASSIST_BYTECODE_PROXY.newProxyInstance(ProxyTestService.class, handler);
        time = System.currentTimeMillis() - time;
        System.out.println("Create JAVASSIST Bytecode Proxy: " + time + " ms");
        time = System.currentTimeMillis();
        ProxyTestService test5 = ProxyEnum.JAVASSIST_DYNAMIC_PROXY.newProxyInstance(ProxyTestService.class, handler);
        time = System.currentTimeMillis() - time;
        System.out.println("Create JAVASSIST Proxy: " + time + " ms");
        String s = "proxy";
        System.out.println("----------------");
        for (int i = 0; i < 10; i++) {
            test(test1, "Run JDK Proxy: ", s);
            test(test2, "Run byteBuddy Proxy: ", s);
            test(test3, "Run CGLIB Proxy: ", s);
            test(test4, "Run JAVASSIST Bytecode Proxy: ", s);
            test(test5, "Run JAVASSIST Proxy: ", s);
            System.out.println("----------------");
        }
    }

    private static void test(ProxyTestService service, String label, String s) {
        service.test(s); // warm up
        int count = 100000000;
        long time = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            service.test(s);
        }
        time = System.currentTimeMillis() - time;
        System.out.println(label + time + " ms, ");
    }
}
